<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>13_生成器-生成器yield语法糖</title>
    <!-- 
  在 JavaScript 中，生成器的  `yield`  语法糖是一个非常强大的特性，它使得生成器函数能够在执行过程中暂停并返回值。
  1. 基本概念
  -  `yield`  关键字用于生成器函数中，允许函数在执行时暂停，并返回一个值给调用者。
  - 当生成器函数被调用时，它不会立即执行，而是返回一个生成器对象。每次调用生成器对象的  `next()`  方法时，函数会执行到下一个  `yield`  语句，然后暂停。

  2. 使用示例
  以下是一个简单的生成器函数示例，展示了  `yield`  的使用：
  function* simpleGenerator() {
      yield 1;
      yield 2;
      yield 3;
  }

  const gen = simpleGenerator();

  console.log(gen.next()); // 输出: { value: 1, done: false }
  console.log(gen.next()); // 输出: { value: 2, done: false }
  console.log(gen.next()); // 输出: { value: 3, done: false }
  console.log(gen.next()); // 输出: { value: undefined, done: true }
  3.  `yield`  的特点
  - 暂停与恢复：每次遇到  `yield`  语句时，生成器函数的执行会暂停，并返回  `yield`  后的值。下次调用  `next()`  方法时，函数将从上次暂停的地方继续执行。
  - 多次调用：可以多次调用  `next()`  方法，直到生成器函数执行完毕，返回  `{ done: true }` 。

  4. 与  `for...of`  循环结合使用
  生成器对象是可迭代的，可以与  `for...of`  循环结合使用，方便地遍历所有  `yield`  返回的值：
  for (const value of simpleGenerator()) {
      console.log(value); // 输出: 1, 2, 3
  }
  5.  `yield`  语法糖的优点
  - 简化代码：使用  `yield`  可以简化异步操作和迭代逻辑，使代码更加清晰易懂。
  - 状态管理：生成器函数可以轻松管理状态，因为它可以在多个  `yield`  之间保存执行上下文。

  6. 总结
  生成器的  `yield`  语法糖提供了一种强大的方式来处理迭代和异步操作。通过  `yield` ，开发者可以方便地暂停和恢复函数的执行，管理复杂的状态和控制流。这使得生成器在处理许多编程场景时变得非常有用，尤其是在需要延迟执行或处理序列数据时。
  --></head>
  <body>
    <script>
      // 1. 生成器函数的语法糖 yield* 表达式
      // const arr = ['a', 'b', 'c'];
      // function* gen(arr) {
      //   yield* arr;
      // }

      // const iterator = gen(arr);
      // console.log(iterator.next());
      // console.log(iterator.next());
      // console.log(iterator.next());
      // console.log(iterator.next());

      // // 2. 生成器函数的语法糖 yield* 表达式
      // function* foo() {
      //   yield 1;
      //   yield 2;
      //   yield 3;
      // }

      // 2. yield* 替换类中实现
      class Person {
        constructor(name, age, friends) {
          this.name = name;
          this.age = age;
          this.friends = friends;
        }

        // 实例方法
        *[Symbol.iterator]() {
          yield this.name;
          yield this.age;
          yield* this.friends;
        }
      }

      const p = new Person("yield", 18, ["kobe", "james", "curry"]);
      for (const item of p) {
        console.log(item); // yield 18 kobe james curry
      }

      const pIterator = p[Symbol.iterator]();
      console.log(pIterator.next());
      console.log(pIterator.next());
      console.log(pIterator.next());
      console.log(pIterator.next());
      console.log(pIterator.next());
    </script>
  </body>
</html>
